/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
 *  Copyright 2008 Global Sign In
 * 
 *  This code is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <libxml/xmlreader.h>
#include <string>

#include "Base64.h"
#include "TestFile.h"

using std::string;

TestFile::TestFile(const string &fileName) :
	MessageDetails(),
	m_fileName(fileName)
{
}

TestFile::~TestFile()
{
}

bool TestFile::parse(void)
{
	xmlDoc *pDoc = NULL;
	xmlNode *pRootElement = NULL;
	bool parsedFile = false;

	if (m_fileName.empty() == true)
	{
		return false;
	}

	// Initialize the library and check potential ABI mismatches between
	// the version it was compiled for and the actual shared library used
	LIBXML_TEST_VERSION

	// Parse the file and get the document
#if LIBXML_VERSION < 20600
	pDoc = xmlParseFile(m_fileName.c_str());
#else
	pDoc = xmlReadFile(m_fileName.c_str(), NULL, XML_PARSE_NOCDATA);
#endif
	if (pDoc != NULL)
	{
		// Get the root element node
		pRootElement = xmlDocGetRootElement(pDoc);

		for (xmlNode *pCurrentNode = pRootElement->children; pCurrentNode != NULL;
			pCurrentNode = pCurrentNode->next)
		{
			// What type of tag is it ?
			if (pCurrentNode->type != XML_ELEMENT_NODE)
			{
				continue;
			}

			// Get the element's content
			char *pContent = (char*)xmlNodeGetContent(pCurrentNode);
			if (pContent == NULL)
			{
				continue;
			}

			// What tag is it ?
			if (xmlStrncmp(pCurrentNode->name, BAD_CAST"subject", 7) == 0)
			{
				m_subject = (const char*)pContent;
			}
			else if ((xmlStrncmp(pCurrentNode->name, BAD_CAST"from", 4) == 0) ||
				(xmlStrncmp(pCurrentNode->name, BAD_CAST"replyto", 7) == 0))
			{
				bool isReplyTo = false;

				if (xmlStrncmp(pCurrentNode->name, BAD_CAST"replyto", 7) == 0)
				{
					isReplyTo = true;
				}

				for (xmlNode *pCurrentFromNode = pCurrentNode->children;
					pCurrentFromNode != NULL; pCurrentFromNode = pCurrentFromNode->next)
				{
					if (pCurrentFromNode->type != XML_ELEMENT_NODE)
					{
						continue;
					}

					char *pChildContent = (char*)xmlNodeGetContent(pCurrentFromNode);
					if (pChildContent == NULL)
					{
						continue;
					}

					if (xmlStrncmp(pCurrentFromNode->name, BAD_CAST"name", 4) == 0)
					{
						if (isReplyTo == false)
						{
							m_fromName = (const char*)pChildContent;
						}
						else
						{
							m_replyToName = (const char*)pChildContent;
						}
					}
					else if (xmlStrncmp(pCurrentFromNode->name, BAD_CAST"emailaddress", 12) == 0)
					{
						if (isReplyTo == false)
						{
							m_fromEmailAddress = (const char*)pChildContent;
						}
						else
						{
							m_replyToEmailAddress = (const char*)pChildContent;
						}
					}

					// Free
					xmlFree(pChildContent);
				}
			}
			else if (xmlStrncmp(pCurrentNode->name, BAD_CAST"sender", 6) == 0)
			{
				m_senderEmailAddress = (const char*)pContent;
			}
			else if (xmlStrncmp(pCurrentNode->name, BAD_CAST"plaintext", 9) == 0)
			{
				m_plainContent = (const char*)pContent;
			}
			else if (xmlStrncmp(pCurrentNode->name, BAD_CAST"html", 4) == 0)
			{
				m_htmlContent = (const char*)pContent;
			}
			else if (xmlStrncmp(pCurrentNode->name, BAD_CAST"attachment", 10) == 0)
			{
				string fileName, attachmentContent;

				for (xmlNode *pCurrentAttachNode = pCurrentNode->children;
					pCurrentAttachNode != NULL; pCurrentAttachNode = pCurrentAttachNode->next)
				{
					if (pCurrentAttachNode->type != XML_ELEMENT_NODE)
					{
						continue;
					}

					char *pChildContent = (char*)xmlNodeGetContent(pCurrentAttachNode);
					if (pChildContent == NULL)
					{
						continue;
					}

					if (xmlStrncmp(pCurrentAttachNode->name, BAD_CAST"filename", 8) == 0)
					{
						fileName = (const char*)pChildContent;
					}
					else if (xmlStrncmp(pCurrentAttachNode->name, BAD_CAST"content", 7) == 0)
					{
						attachmentContent = (const char*)pChildContent;
					}

					// Free
					xmlFree(pChildContent);
				}

				if (attachmentContent.empty() == false)
				{
					m_attachments.push_back(new Attachment(fileName,
						attachmentContent.c_str(),
						(unsigned long)attachmentContent.length()));
				}
			}

			// Free
			xmlFree(pContent);
		}

		// Free the document
		xmlFreeDoc(pDoc);

		parsedFile = true;
	}

	// Cleanup
	xmlCleanupParser();

	return parsedFile;
}

